import { IcosahedronGeometry,Vector2, TextureLoader, ShaderMaterial, Mesh, ShaderChunk } from '../libs/three137/three.module.js';
import { noise } from '../libs/Noise.js';
import { Tween } from '../libs/Toon3D.js';
import { urls } from '../assets/store.js';

class Explosion{
  static vshader =/*glsl*/ `
#include <noise>

uniform float u_time;

varying float noise;

void main() {	
  float time = u_time;
  float displacement;
  float b;
  
  // add time to the noise parameters so it's animated
  noise = 10.0 *  -.10 * turbulence( .5 * normal + time );
  b = 5.0 * pnoise( 0.05 * position + vec3( 2.0 * time ), vec3( 100.0 ) );
  displacement = - 10. * noise + b;

  // move the position along the normal and transform it
  vec3 newPosition = position + normal * displacement;
  gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
`
  static fshader = /*glsl*/`
#define PI 3.141592653589
#define PI2 6.28318530718

uniform vec2 u_mouse;
uniform vec2 u_resolution;
uniform float u_time;
uniform float u_opacity;
uniform sampler2D u_tex;

varying float noise;

//	<https://www.shadertoy.com/view/4dS3Wd>
//	By Morgan McGuire @morgan3d, http://graphicscodex.com

//https://www.clicktorelease.com/blog/vertex-displacement-noise-3d-webgl-glsl-three-js/

float random( vec3 scale, float seed ){
  return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed ) ;
}

void main() {

  // get a random offset
  float r = .01 * random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );
  // lookup vertically in the texture, using noise and offset
  // to get the right RGB colour
  vec2 t_pos = vec2( 0, 1.3 * noise + r );
  vec4 color = texture2D( u_tex, t_pos );

  gl_FragColor = vec4( color.rgb, u_opacity );
}
`


  constructor(parent, obstacles){
    console.log('爆炸开始');
    // this.explosions =new Set()    ;
    this.obstacles = obstacles ;
    // 20 面体，                          半径 额外顶点
    const geo  = new IcosahedronGeometry(20, 4) ; 

    this.uniforms  ={ 
      u_time:{value:0},
      u_mouse:{value:new Vector2()},
      u_opacity:{value:0.6},
      u_resolution: {value: new Vector2()} ,
      u_tex: {value:  new TextureLoader().load('../assets/plane/explosion.png')}
    }

    ShaderChunk.noise = noise ;

    const mat = new ShaderMaterial({ 
      uniforms:this.uniforms ,
      vertexShader: Explosion.vshader ,
      fragmentShader: Explosion.fshader ,
      transparent: true ,
      opacity: .6 
    })

    this.ball = new Mesh( geo, mat) ;
    this.ball.scale.set(.05,.05,.05)  ;
    parent.add(this.ball) ;
    console.log(parent);
    this.tweens = [];
                  //target, channel, endValue, duration, oncomplete, easing="inOutQuad"
    this.tweens.push(new Tween(this.ball.scale, 'x', .2, 1.5 , this.onComplete.bind(this), 'outQuad'))
    this.active =true 
  }
  

  // 爆炸结束
  onComplete(){
    this.ball.parent.remove(this.ball) ;
    this.tweens = [] ;
    this.active = false ;
    this.ball.geometry.dispose() ;
    this.ball.material.dispose() ;
    if(this.obstacles) this.obstacles.removeExplosion(this) ;
    console.log('爆炸结束');
  }

  update(dt) {
    // 这个时间应该是一个相对于初始化的时间
    if(!this.active){ return}
    


    console.log(dt , '爆炸中',this.ball.scale.x);
    this.uniforms.u_opacity.value  = this.ball.material.opacity ;
    this.uniforms.u_time.value+=dt ;
    if(this.tweens.length < 2){ // tweems 内最多只会有 透明度 和 scale.x 过渡
      // elapse 你& vi 时间过去 流逝
      const elapsedTime  = this.uniforms.u_time.value -1 ;
      if(elapsedTime > 0){  // 延后一点设置透明度渐变
        this.tweens.push( new Tween(this.ball.material, 'opacity', 0, .5))
      }
    }
    // upadate接受的是dt 
    this.tweens.forEach((tween ) => { tween.update(dt)}) // 就是输入时间 得到对应的节点值
    let s = this.ball.scale.x ;
    this.ball.scale.set(s,s,s)
  }

}

export { Explosion };